﻿package framework.core;

import java.text.SimpleDateFormat;
import java.util.*;
/**
 * Creation date: (2003-08-28)
 * @author: adminnistrator
 * 时间类
 * Format : YYYY-MM-DD HH_MM_SS  	
 */
 
 
 
public class DateUtil 
{
	private static String DATE_DIVISION      = "-" ; // 日期分割符
	private static String TIME_DIVISION      = ":" ; // 时间分割符
	private static String DATE_TIME_DIVISION = " " ; // 日期和时间的分割符

	private int m_year  ;
	private int m_month  ;
	private int m_day  ;
	private int m_hour  ;
	private int m_minute;
	private int m_second ;
	
	public static final int DAY = 4;
	public static final int HOUR = 3;
	public static final int MINUTE = 2;
	public static final int SECOND = 1;

//format : YYYY-MM-DD HH-MM-SS
public DateUtil() 
{
	GregorianCalendar now = new  GregorianCalendar();
	m_year = now.get(Calendar.YEAR);
	m_month = now.get(Calendar.MONTH)+1;
	m_day = now.get(Calendar.DAY_OF_MONTH);
	m_hour = now.get(Calendar.HOUR_OF_DAY);
	m_minute = now.get(Calendar.MINUTE);
	m_second = now.get(Calendar.SECOND);

}
//format : YYYY-MM-DD HH-MM-SS
public DateUtil(int year,int month,int day,int hour,int minute,int second)  throws Exception
{
	if(!isValid(year,month,day,hour,minute,second))
	{
		throw new Exception("DateUtil("+year+","+month+","+day+","+hour+","+minute+","+second+"):无效的日期格式");
	}
	m_year = year ;
	m_month = month ;
	m_day = day ;
	m_hour = hour ;
	m_minute = minute;
	m_second = second ;
}

public DateUtil(int year,int month,int day)  throws Exception
{
	this(year,month,day,0,0,0);
}

//format : YYYY-MM-DD HH-MM-SS
public DateUtil(DateUtil date) throws Exception
{
	if(date==null)
	{
		throw new Exception("DateUtil("+date+"):无效参数!");
	}
	if(!date.isValid())
	{
		throw new Exception("DateUtil("+date+"):无效参数!");
	}
	m_year = date.m_year ;
	m_month = date.m_month ;
	m_day = date.m_day ;
	m_hour = date.m_hour ;
	m_minute = date.m_minute;
	m_second = date.m_second ;

}
//format : YYYY-MM-DD HH-MM-SS
public DateUtil(String date)  throws Exception
{
	int[] r = getDateFields(date);
	m_year = r[0] ;
	m_month = r[1] ;
	m_day   = r[2] ;
	m_hour  = r[3] ;
	m_minute = r[4] ;
	m_second = r[5] ;

	if(!isValid(m_year,m_month,m_day,m_hour,m_minute,m_second))
	{
		throw new Exception("DateUtil("+date+"):无效的日期格式");
	}
}
//format : YYYY-MM-DD HH-MM-SS
public DateUtil(java.sql.Date date) throws Exception
{
	String s = date.toString();
	int[] r = getDateFields(s);
	m_year = r[0] ;
	m_month = r[1] ;
	m_day   = r[2] ;
	m_hour  = r[3] ;
	m_minute = r[4] ;
	m_second = r[5] ;

	if(!isValid(m_year,m_month,m_day,m_hour,m_minute,m_second))
	{
		throw new Exception("DateUtil("+date.toString()+"):无效的日期格式");
	}
}
public void advanceDays(int days)
{
	fromJulian(toJulian()+days);
}
public int daysBetween(DateUtil b)
{
	return toJulian() - b.toJulian();
}
	public boolean equals(Object v)
	{
		if(v==null) return false;
		if(!(v instanceof DateUtil))
		{
			return false;
		}
		DateUtil d = (DateUtil)v;
		return (m_year==d.m_year &&
			    m_month==d.m_month &&
			    m_day==d.m_day &&
			    m_hour==d.m_hour &&
			    m_minute==d.m_minute &&
			    m_second==d.m_second);
	}
/**
	  Converts a Julian day to a calendar date

	  This algorithm is from Press et al., Numerical Recipes
	  in C, 2nd ed., Cambridge University Press 1992
	  
	  @param j  the Julian date
*/
	
private void fromJulian(int j)
{
	int ja = j;
   
	int JGREG = 2299161;
	/* the Julian date of the adoption of the Gregorian
		calendar    
	*/   

	if (j >= JGREG)
	/* cross-over to Gregorian Calendar produces this 
		 correction
	*/   
	{  int jalpha = (int)(((float)(j - 1867216) - 0.25) 
		 / 36524.25);
		 ja += 1 + jalpha - (int)(0.25 * jalpha);
	}
	int jb = ja + 1524;
	int jc = (int)(6680.0 + ((float)(jb-2439870) - 122.1)
		  /365.25);
	  int jd = (int)(365 * jc + (0.25 * jc));
	  int je = (int)((jb - jd)/30.6001);
	  m_day = jb - jd - (int)(30.6001 * je);
	  m_month = je - 1;
	  if (m_month > 12) m_month -= 12;
	  m_year = jc - 4715;
	  if (m_month > 2) --m_year;
	  if (m_year <= 0) --m_year;
   }
public DateUtil getAdvanceDays(int days) throws Exception
{
	DateUtil r = new DateUtil(this);
	r.advanceDays(days);
	return r;
}
private static int[] getDateFields(String t) throws Exception
{
	String[]  dayAndtime = getStringsFromStr(t,DATE_TIME_DIVISION);
	if(dayAndtime.length!=2 && dayAndtime.length!=1)
	{
		throw new Exception("DateUtil.getDateFields("+t+"):无效的日期格式");   //exit,不是由日期和时间组成
	}
	
	//0 is year,1 is month ,2 is day
	int[] dates = getIntsFromStr(dayAndtime[0],DATE_DIVISION);
	if(dates.length!=3)
	{
	   throw new Exception("DateUtil.getDateFields("+t+"):无效的日期格式");
	}

	int[] times;
	times = new int[3];

	if(dayAndtime.length==2)
	{
		//0 is hour,1 is minute ,2 is second
		int[] ts = getIntsFromStr(dayAndtime[1],TIME_DIVISION);
		if(ts.length>3)
		{
			throw new Exception("DateUtil.getDateFields("+t+"):无效的日期格式");
		}

		if(ts.length==1) 
		{
			times[0] = ts[0] ;
			times[1] = 0 ;
			times[2] = 0 ;
		}
		if(ts.length==2) 
		{
			times[0] = ts[0] ;
			times[1] = ts[1] ;
			times[2] = 0 ;
		}
		if(ts.length==3) 
		{
			times[0] = ts[0] ;
			times[1] = ts[1] ;
			times[2] = ts[2] ;
		}
	}
	else
	{
		times[0] = 0 ;
		times[1] = 0 ;
		times[2] = 0 ;
	}
	
	int[]  r = new int[6];
	r[0] = dates[0];
	r[1] = dates[1];
	r[2] = dates[2];
	r[3] = times[0];
	r[4] = times[1];
	r[5] = times[2];
	return r ;
	
}
public String getDateString()
{
	String  affMonth = m_month<10 ? "0"+String.valueOf(m_month):String.valueOf(m_month);
	String  affDay   = m_day<10   ? "0"+String.valueOf(m_day):String.valueOf(m_day);
	
	return String.valueOf(m_year)  + DATE_DIVISION +
	       affMonth + DATE_DIVISION +
		   affDay ;
}
public int getDay()
{
	return m_day ;
}
public String getFullString()
{
	String  affMonth = m_month<10 ? "0"+String.valueOf(m_month):String.valueOf(m_month);
	String  affDay   = m_day<10   ? "0"+String.valueOf(m_day):String.valueOf(m_day);
	String  affHour  = m_hour<10   ? "0"+String.valueOf(m_hour):String.valueOf(m_hour);
	String  affMinute = m_minute<10   ? "0"+String.valueOf(m_minute):String.valueOf(m_minute);
	String  affSecond = m_second<10   ? "0"+String.valueOf(m_second):String.valueOf(m_second);
	
	return String.valueOf(m_year)  + DATE_DIVISION +
	       affMonth + DATE_DIVISION +
		   affDay   + DATE_TIME_DIVISION +
		   affHour  + TIME_DIVISION +
		   affMinute+ TIME_DIVISION +
		   affSecond ;
}
public int getHour()
{
	return m_hour ;
}
/*
   example:
   str = "1:2:3:4:" ; token=":" ;
   return  int[4] , [0]=1,[1]=2,[2]=3,[3]=4
*/
private static int[] getIntsFromStr(String str,String token)
{
	StringTokenizer st = new StringTokenizer(str,token);
	Vector v = new Vector();
	while (st.hasMoreTokens()) 
 	{
	    v.add(st.nextToken());
	}
 	int[] ints = new int[v.size()];
 	for(int i=0;i<v.size();i++)
 	{
	 	ints[i] = Integer.parseInt((String)v.get(i));
 	}
 	return ints;
}
public int getMinute()
{
	return m_minute;
}
public int getMonth()
{
	return m_month;
}
public DateUtil getMonthEnd() throws Exception
{
	DateUtil r = getMonthStart();
	if(r.getMonth()==1 ||
	   r.getMonth()==3 ||
	   r.getMonth()==5 ||
	   r.getMonth()==7 ||
	   r.getMonth()==8 ||
	   r.getMonth()==10||
	   r.getMonth()==12)
	{
		r.advanceDays(30);
	} 
	if(r.getMonth()==4 ||
	   r.getMonth()==6 ||
	   r.getMonth()==9 ||
	   r.getMonth()==11)
	{
		r.advanceDays(29);
	}
	if(r.getMonth()==2)
	{
	   int year = r.getYear();
	   
	   if (0==year%4 && (year%100)!=0 || 0==year%400)//闰年 
	   {
		   r.advanceDays(28);
	   }
	   else//非闰年 
	   {
		   r.advanceDays(27);
	   }
	}
	    
	return r ;
}
public DateUtil getMonthStart() throws Exception
{
	return new DateUtil(m_year,m_month,1,0,0,0) ;
}
public int getQuarter()
{
	return (m_month+2)/3;
}
public int getSecond()
{
	return m_second ;
}
public  java.sql.Date getSqlDate()
{
	return java.sql.Date.valueOf(getDateString());
}
private static String[] getStringsFromStr(String str,String token)
{
	StringTokenizer st = new StringTokenizer(str,token);
	Vector v = new Vector();
	while (st.hasMoreTokens()) 
 	{
	    v.add(st.nextToken());
	}
 	String[] strs = new String[v.size()];
 	for(int i=0;i<v.size();i++)
 	{
	 	strs[i] = (String)v.get(i);
 	}
 	return strs;
}
public String getTimeString()
{
	String  affHour  = m_hour<10   ? "0"+String.valueOf(m_hour):String.valueOf(m_hour);
	String  affMinute = m_minute<10   ? "0"+String.valueOf(m_minute):String.valueOf(m_minute);
	String  affSecond = m_second<10   ? "0"+String.valueOf(m_second):String.valueOf(m_second);

	
	return affHour   + TIME_DIVISION +
		   affMinute + TIME_DIVISION +
		   affSecond ;
}
public int getWeekDay() throws Exception
{
	//2000-1-3 星期1
	DateUtil std = new DateUtil("2000-1-3");
	int days = daysBetween(std);
	int m = days % 7 ;
	
	if(m>=0)
	{
		return m+1;
	}
	else
	{
		return m+8;
	}
}
public DateUtil getWeekEnd() throws Exception
{
	DateUtil r = getWeekStart();
	r.advanceDays(7);
	return r;
}
public DateUtil getWeekStart() throws Exception
{
	//2000-1-3 星期1
	DateUtil std = new DateUtil("2000-1-3");
	int days = daysBetween(std);
	int m = days % 7 ;
	DateUtil r ;
	if(m>=0)
	{
		r = getAdvanceDays(-m);
	}
	else
	{
		r = getAdvanceDays(-m-7);
	}
	return r;
}
public int getYear()
{
	return m_year;
}
public boolean isValid()
{
	return isValid(m_year,m_month,m_day,m_hour,m_minute,m_second);
}//valid format : YYYY-MM-DD HH-MM-SS or
//format : YYYY-MM-DD HH-MM-SS
public static boolean isValid(int year,int month,int day,int hour,int minute,int second) 
{
	//time check
	if( hour<0 || hour>23 || minute<0 || minute>59 || second<0 || second>59)
	{
		return false; 
	}

	//date check 
	if ( year < 0 || month<1 || month > 12 || day<1 || day>31)
	{
		return false ;
	}
	switch(month)
	{
		case 1:
		case 3:
		case 5:
		case 7:
		case 8:
		case 10:
		case 12:   
		   return true ;  
		case 4:
		case 6:
		case 9:
		case 11:
		   if (day>30) return false ;  
		   return true ;               
		case 2 :
		   //闰年
		   if (0==year%4 && (year%100)!=0 || 0==year%400)
		   {
			   if (day>29) return false ; 
			   return true ;          
		   }
		   //非闰年 
		   if (day>28) return false ; 
		   return true ;    
		default:
		   return false ;   
	}
}
//               YYYY-MM-DD 
public static boolean isValid(String sDate) throws Exception
{
	int[] r ;
	try
	{
		r = getDateFields(sDate);
	}
	catch(Exception e)
	{
		return false;
	}
	return isValid(r[0],r[1],r[2],r[3],r[4],r[5]);
}
/**
	  @return The Julian day number that begins at noon of 
	  this day
	  Positive year signifies A.D., negative year B.C. 
	  Remember that the year after 1 B.C. was 1 A.D.

	  A convenient reference point is that May 23, 1968 noon
	  is Julian day 2440000.

	  Julian day 0 is a Monday.

	  This algorithm is from Press et al., Numerical Recipes
	  in C, 2nd ed., Cambridge University Press 1992
	*/
private int toJulian()
{  
	  int jy = m_year;
	  if (m_year < 0) jy++;
	  int jm = m_month;
	  if (m_month > 2) jm++;
	  else
	  {  jy--;
		 jm += 13;
	  }
	  int jul = (int) (java.lang.Math.floor(365.25 * jy) 
	  + java.lang.Math.floor(30.6001*jm) + m_day + 1720995.0);

	  int IGREG = 15 + 31*(10+12*1582);
   	  // Gregorian Calendar adopted Oct. 15, 1582

	  if (m_day + 31 * (m_month + 12 * m_year) >= IGREG)
  	  // change over to Gregorian calendar
	  {  int ja = (int)(0.01 * jy);
		 jul += 2 - ja + (int)(0.25 * ja);
	  }
	  return jul;
}
public String toString()
{
	return getFullString();
}

public static String viewDate(String d) throws Exception
{
	try
	{
		DateUtil date = new DateUtil(d);
		return date.getDateString();
	}
	catch(Exception e)
	{
		return "";
	}
}

//----add by twb @2004-06-09 ------//
private static DateUtil getDateStart(String date) throws Exception
{
	DateUtil d = new DateUtil(date);
	return d ;
}
private static DateUtil getDateEnd(String date) throws Exception
{
	DateUtil d = new DateUtil(date);
	d.m_hour = 23 ;
	d.m_minute = 59 ;
	d.m_second = 59 ;
	return d ;
}
public static String getDateStartStr(String date) throws Exception
{
	return getDateStartStr(new DateUtil(date));
}

public static String getDateStartStr(DateUtil date) throws Exception
{
	return date.getDateString();
}
public String getDateStartStr() throws Exception 
{
	return getDateStartStr(this);
}

public static String getDateEndStr(String date) throws Exception
{
	return getDateEndStr(new DateUtil(date)); 
}
public static String getDateEndStr(DateUtil date) throws Exception
{
	DateUtil d = new DateUtil(date.getYear(),date.getMonth(),date.getDay(),23,59,59);
	return d.getFullString(); 
}
public String getDateEndStr() throws Exception 
{
	return getDateEndStr(this);
}

public static String viewChineseDate(String date) throws Exception
{
	if(date==null||date.equals("")) return "";
	DateUtil d = new DateUtil(date);
	return ""+d.getYear()+"年"+d.getMonth()+"月"+d.getDay()+"日";
}
public String viewChineseDate() throws Exception
{
	return ""+getYear()+"年"+getMonth()+"月"+getDay()+"日";	
}
public DateUtil getNextMonthStartDate() throws Exception 
{
	if(getMonth()==12) return new DateUtil(getYear()+1,1,1);
	return new DateUtil(getYear(),getMonth()+1,1);
	
}

public DateUtil getPreDay() throws Exception
{
	if(getMonth() == 1 && getDay() == 1)
		return new DateUtil(getYear()-1, 12, 31);
	if(getMonth() != 1 && getDay() == 1)	
		return new DateUtil(getYear(), getMonth()-1, 1).getMonthEnd();
	return new DateUtil(getYear(), getMonth(), getDay()-1);
}

//  return value :  0 两个时间相等
//               ： 1 时间大 
//               ： -1 时间小 
public int compare(DateUtil d) 
{
	if(getYear()>d.getYear()) return 1 ;
	if(getYear()<d.getYear()) return -1 ;
	if(getMonth()>d.getMonth()) return 1 ;
	if(getMonth()<d.getMonth()) return -1 ;
	if(getDay()>d.getDay()) return 1 ;
	if(getDay()<d.getDay()) return -1 ;
	if(getHour()>d.getHour()) return 1 ;
	if(getHour()<d.getHour()) return -1 ;
	if(getMinute()>d.getMinute()) return 1 ;
	if(getMinute()<d.getMinute()) return -1 ;
	if(getSecond()>d.getSecond()) return 1 ;
	if(getSecond()<d.getSecond()) return -1 ;
	return 0 ;
}

public boolean greaterEqual(DateUtil d) 
{
	if(compare(d)==0 || compare(d)==1) return true ;
	return false;
}
public boolean lessEqual(DateUtil d) 
{
	if(compare(d)==0 || compare(d)==-1) return true ;
	return false;
}
public boolean greater(DateUtil d) 
{
	return (compare(d)==1);
}
public boolean less(DateUtil d) 
{
	return (compare(d)==-1);
}
public boolean isBetween(DateUtil startTime,DateUtil endTime)
{
	if( greaterEqual(startTime) && lessEqual(endTime)) return true;
	return false;
}

public DateUtil add(int field, int amount) throws Exception
{
	GregorianCalendar gc = new GregorianCalendar(getYear(), getMonth()-1, getDay());
	gc.add(field, amount);
	return new DateUtil(gc.get(Calendar.YEAR), gc.get(Calendar.MONTH)+1, gc.get(Calendar.DATE));
}

//----end

// add by Jackey start
/**
 * 取得某年月的最大天数
 * @param year
 * @param month
 * @return
 * @throws Exception
 */
public static int getMaxDayOfMonth(int year,int month) throws Exception{
    Calendar tCalendar = Calendar.getInstance();
    tCalendar.clear();
    tCalendar.set(Calendar.YEAR, year);
    tCalendar.set(Calendar.MONTH, month - 1);

    return tCalendar.getActualMaximum(Calendar.DAY_OF_MONTH);

}

/**
 * 将yyyyMMddhhmmss格式化为 yyyy-MM-dd hh:mm:ss
 * @param val
 * @return
 * @throws Exception
 */
public static String formatToLongDateString(String val,String defVal) throws Exception
{
    String mReturn = "";
    try{
        mReturn = val.substring(0, 4) + "-" + val.substring(4, 6) + "-" + val.substring(6, 8)
                + " "
                + val.substring(8,10) + ":" + val.substring(10,12) + ":" + val.substring(12,14);
    }catch(Exception e)
    {
        mReturn = defVal;
    }
    return mReturn;
}
// add by Jackey end

/**
 * fields: 1 代表 秒（DateUtil.SECOND）
 *         2 代表 分钟（DateUtil.MINUTE）
 *         3 代表 小时（DateUtil.HOUR）
 *         4 代表 天（DateUtil.DAY）
 */
public static long getBetween(int fields, String startTime, String endTime){
    long ret = 0;
    
    try{
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date start = sdf.parse(startTime);
        Date end = sdf.parse(endTime);
        long diff = (end.getTime() - start.getTime()) / 1000;
        switch(fields) {
        case DateUtil.DAY:
            ret = diff / 24 * 3600;
            break;
        case DateUtil.HOUR:
            ret = diff / 3600;
            break;
        case DateUtil.MINUTE:
            ret = diff / 60;
            break;
        case DateUtil.SECOND:
            ret = diff;
            break; 
        default:
            ret = 0;
            break;
        }
    }
    catch(Exception e){
        e.printStackTrace();
        ret = 0;
    }
    
    return ret;
}

}
